package com.xs.servlet;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import com.xs.listenner.MyUploadListener;
import com.xs.util.VideoUtil;

@WebServlet("/UploadServlet")
public class UploadServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//文件上传
		// 设置请求跟相应的编码
		request.setCharacterEncoding("Utf-8");
		response.setCharacterEncoding("Utf-8");
		// 实例化一个硬盘文件工厂，用来配置上传组件ServletFileUpload
		// 硬盘文件项工厂--这里注意导包不要导错了,这个统一格式为:import org.apache.commons.fileupload
		DiskFileItemFactory dif = new DiskFileItemFactory();
		// 用以上工厂实例化上传组件: 建立关联
		ServletFileUpload sf = new ServletFileUpload(dif);
		// 添加上传监听器----MyUploadListener（）在com.xs.listenner包下
		sf.setProgressListener(new MyUploadListener(request));
		//在服务器拿到该项目的路径,好在后面加上我们需要的路径地址
		String path=this.getServletConfig().getServletContext().getRealPath("//");
		try {
			// 解析request,用list集合接收并遍历得到请求中所有上传域的列表,即表单里面的每一个值都作为文件项上传,
			// 请求里面传过来的request请求一个是text,一个是file文件,这两个值分别装进list集合再for循环遍历判断是否是普通表单还是文件
			List list = sf.parseRequest(request);
			for (int i = 0; i < list.size(); i++) {
				FileItem item = (FileItem) list.get(i);
				if (item.isFormField()) { // 判断是否是普通表单域还是文件上传表单域。
					// 普通类型文件
					// getName方法用来获得文件上传字段中的文件名。
					System.out.println(item.getFieldName());
					// getFieldName方法用来返回表单标签的name属性的值。
					System.out.println(item.getName());
					// 将FileItem对象中保存的数据流内容以一个字符串返回。
					System.out.println(item.getString());
				} else {
					// 不是普通类型文件,先拿到文件名
					String fileName = item.getName();
					// lastIndexOf() 方法可返回一个指定的字符串值最后出现的位置，在一个字符串中的指定位置从后向前搜索。
					int num = fileName.lastIndexOf("\\"); // 搜索以"\\"为索引最后出现的位置,当出现-1,说明没找到"\\"
					if (num != -1) {
						// 用substring() 方法截取到:/文件名.---这里num+1就是把文件名前面的/去掉
						fileName = fileName.substring(num + 1);
					}
					// System.out.println(item.getName());--------测试用
					// 将上传的文件名存储到session中,便于sql添加
					request.getSession().setAttribute("fileName", fileName);

					// 到这一步,我们拿到了所有的文件名
					// 输入输出都是针对于程序: 输入:程序拿到一个流信息(文件), 输出:程序向外创建文件-----拓展内容:什么是输入输出流
					// 这里是拿到一个流信息(文件)
					InputStream in = item.getInputStream();
					// 方式一: 在服务器端将该文件保存在:"C:\\Users\\admin\\Desktop"即服务器的保存地址.我们的TOMCAT就是服务器
					// String path = "C:\\Users\\admin\\Desktop";-----不可取的固定路径

					// 方式二:动态的路径
					File  f=new File(path+"/videos//"+fileName);
					System.out.println(f);
					// 方式三:动态的路径和二基本一样,就位置而已
//					String path = this.getServletContext().getRealPath("videos");
//					System.out.println(path);
//					// 将文件上传到该路径下
//					File f = new File(path + "//" + fileName);
					// 通过输出流向指定位置输出
					OutputStream out = new FileOutputStream(f);
					// 到这一步,已经将上传的文件传到服务器的路径地址给打通了,下面开始读跟写入文件
					byte[] b = new byte[in.available()];// in.available()方法返回的实际可读字节数，也就是总大小
					// 将文件信息读到数组中,这里用的是最原始的读取跟写入,也可以用缓冲流进行读取写入---IO流教学内容深入学习下
					in.read(b);
					// 将文件写到指定位置
					out.write(b);
					// 清除session里面的记录
					request.getSession().removeAttribute("size");
					request.getSession().removeAttribute("countSize");
					// 文件刷新
					out.flush();
					// 关闭--此时就完成了文件上传功能
					out.close();
					// 视频文件格式转换
					// 第一步:得到文件路径,记住这里的路径是服务器路径，不是项目地址
					// 需转换的文件的位置等同于D:\\Tomcat\\wtpwebapps\\VideoPlayback\\videos\\fileName
					String inputFile_home = path + "/videos//"+fileName;
					// 这里截取掉文件格式再加我们需要的后缀格式,文件格式转换不支持改文件名
					fileName = fileName.substring(0, fileName.lastIndexOf("."));
					// 转换后的flv文件所放的文件夹位置
					String outputFile_home = path +"/videos//"+fileName + ".flv";
					// 得到mencoder.exe跟ffmpeg.exe所放的路径
					String mencoder_home = this.getServletContext().getRealPath("tools/mencoder.exe");
					String ffmpeg_home = this.getServletContext().getRealPath("tools/ffmpeg.exe");
					// 有参构造函数实例化,就是吧上面得到的路径存入vu
					VideoUtil vu = new VideoUtil(mencoder_home, ffmpeg_home);
					// 调用转换方法
					vu.convert(inputFile_home, outputFile_home);
				}
			}
		} catch (FileUploadException e) {
			e.printStackTrace();
		}

	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}
